#include <func.h>

typedef struct {
    int id;
    char name[25];
    int balance;
    pthread_mutex_t mutex;  // 细粒度锁
} Account;

Account acct1 = {1, "peanut", 100, PTHREAD_MUTEX_INITIALIZER};
Account acct2 = {2, "xixi", 999999999, PTHREAD_MUTEX_INITIALIZER};

pthread_mutex_t protect = PTHREAD_MUTEX_INITIALIZER;

void* transfer(Account* acctA, Account* acctB, int money) 
{
    pthread_mutex_lock(&protect);
    pthread_mutex_lock(&acctA->mutex);
    sleep(1);
    pthread_mutex_lock(&acctB->mutex);
    pthread_mutex_unlock(&protect);
    
    if(acctA->balance < money) {
        pthread_mutex_unlock(&acctA->mutex);
        pthread_mutex_unlock(&acctB->mutex);
        return 0;
    }

    acctA->balance -= money;
    acctB->balance += money;

    pthread_mutex_unlock(&acctA->mutex);
    pthread_mutex_unlock(&acctB->mutex);
    return (void*)money;
}

void* start_routine1(void* arg)
{
    int money = transfer(&acct1, &acct2, (int)arg); 
    printf("%s -> %s: %d\n", acct1.name, acct2.name, money);
    return NULL;
}

void* start_routine2(void* arg)
{
    int money = transfer(&acct2, &acct1, (int)arg); 
    printf("%s -> %s: %d\n", acct2.name, acct1.name, money);
    return NULL;
}

int main(int argc, char* argv[])
{
    pthread_t tid1, tid2;
    pthread_create(&tid1, NULL, start_routine1, (void*)100);
    pthread_create(&tid2, NULL, start_routine2, (void*)999);

    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);
    return 0;
}

